精通Linux系列十二:从两个1000000行的文件里找出差异行(文件比较)
精通Linux系列点击关注公众号,AI&编程干货及时送达
文件比较
命令 | 含义 |
diff | 比较两个文件或目录的逐行差异。 |
comm | 比较两个已排序文件的逐行差异。 |
cmp | 比较两个文件的逐字节差异。 |
md5sum | 计算给定文件的校验和(MD5)。 |
在Linux中有三种方法可以比较文件:
• 逐行比较 (
diff
,diff3
,sdiff
,comm
),最适合文本文件• 逐字节比较 (
cmp
),通常用于二进制文件• 通过比较校验和进行比较 (
md5sum
,sum
,cksum
)
diff
stdin stdout - file -- opt --help --version
diff [选项] file1 file2
diff
命令逐行比较两个文件(或两个目录)。当比较文本文件时,diff
可以生成详细的差异报告。对于二进制文件,diff
只会报告它们是否有差异。对于所有文件,如果没有差异,diff
不会产生任何输出。
传统的输出格式如下:
指示行号和更改类型
< 文件1的对应部分(如果有的话)
> 文件2的对应部分(如果有的话)
例如,如果我们开始一个叫fileA的文件:
你好,这是一个很棒的文件。
快速的棕色狐狸跳过了
懒狗。
再见。
假设我们删除了第一行,将第二行的"棕色"改为"蓝色",并添加了一行,生成一个叫fileB的文件:
快速的蓝色狐狸跳过了
懒狗。
再见。
Linux是最棒的!
那么diff
命令会为这些文件生成如下输出:
→ diff fileA fileB
1,2c1 fileA的第1-2行变成了fileB的第1行
< 你好,这是一个很棒的文件。 fileA的第1-2行
< 快速的棕色狐狸跳过了
``` diff分隔符
> 快速的蓝色狐狸跳过了 fileB的第1行
4a4 在fileB中添加了第4行
> Linux是最棒的! 添加的行
前导符号<和>是箭头,分别指示fileA和fileB。这个输出格式是默认的:还有许多其他可用的选项,其中一些可以直接供给其他工具使用。
选项 | 输出格式 |
-n | RCS版本控制格式,由rcsdiff (man rcsdiff )产生。 |
-c | 上下文差异格式,被patch 命令(man patch )使用。 |
-D 宏 | C预处理器格式,使用#ifdef 宏 ... #else ... #endif 。 |
-u | 统一格式,合并文件并在删除前添加“-”,在添加时添加“+”。 |
-y | 并排格式;使用-W 来调整输出的宽度。 |
-e | 创建一个ed 脚本,如果运行,会将fileA变成fileB。 |
-q | 不报告更改,只是说文件是否有差异。 |
diff
也可以比较目录:
→ diff dir1 dir2
这将比较这些目录中的任何同名文件,并列出所有出现在一个目录中但不在另一个目录中的文件。要递归比较整个目录层次结构,使用-r
选项:
→ diff -r dir1 dir2
这将产生一个(可能巨大的)所有差异的报告。
有用的选项
-b | 不考虑空格。 |
-B | 不考虑空行。 |
-i | 忽略大小写。 |
-r | 在比较目录时,递归进入子目录。 |
diff
只是一个操作文件差异的程序家族中的一个成员。其他的一些成员包括diff3
,一次比较三个文件,以及sdiff
,根据你的指示将两个文件的差异合并到第三个文件中。
comm
stdin stdout - file -- opt --help --version
comm [选项] 文件1 文件2
comm
命令比较两个已排序的文件,并产生三列输出,由制表符分隔:
1. 所有出现在文件1中但不在文件2中的行。
2. 所有出现在文件2中但不在文件1中的行。
3. 在两个文件中都出现的所有行。
例如,如果commfile1和commfile2包含以下行:
commfile1: commfile2:
苹果 面包师傅
面包师傅 查理
查理 黑暗
然后comm
产生这个三列的输出:
→ comm commfile1 commfile2
苹果
面包师傅
查理
黑暗
有用的选项
-1 | 抑制第1列。 |
-2 | 抑制第2列。 |
-3 | 抑制第3列。 |
-23 | 只显示出现在第一个文件中的行。 |
-13 | 只显示出现在第二个文件中的行。 |
-12 | 只显示公共行。 |
cmp
标准输入 标准输出 - 文件 -- 选项 --帮助 --版本
cmp [选项] 文件1 文件2 [偏移量1 [偏移量2]]
cmp
命令比较两个文件。如果它们的内容相同,cmp
不报告任何东西;否则,它列出第一个差异的位置:
→ cmp 我的文件 你的文件
我的文件 你的文件有差异:字节225,行4
默认情况下,cmp
不告诉你差异是什么,只告诉你差异在哪里。它也非常适合比较二进制文件,与diff
不同,diff
在处理文本文件时效果最好。
通常,cmp
从每个文件的开始处开始比较,但如果你提供了偏移量,它会从其他地方开始:
→ cmp 我的文件 你的文件 10 20
这在我的文件的第十个字符和你的文件的第二十个字符处开始比较。
有用的选项
-l | 长输出:打印所有差异,按字节打印:→ **cmp -l 我的文件 你的文件** 225 167 127 这意味着在偏移量225(以十进制计),我的文件有一个小“w”(八进制167)但你的文件有一个大写的“W”(八进制127)。 |
-s | 静默输出:不打印任何东西,只是以一个适当的返回码退出;如果文件匹配,返回码为0,如果不匹配,返回码为1。(如果比较失败,可能会有其他代码。) |
md5sum
标准输入 标准输出 - 文件 -- 选项 --帮助 --版本
md5sum 文件 | --check 文件
md5sum
命令用校验和来验证文件是否未改变。第一种形式使用MD5算法产生给定文件的32字节校验和:
→ md5sum 我的文件
48760f921ec6111e3979efa14e22535d 我的文件
第二种形式测试校验和是否与其文件匹配,使用--check
:
→ md5sum 我的文件 我的文件2 我的文件3 > 我的总和
→ cat 我的总和
48760f921ec6111e3979efa14e22535d 我的文件
49f6c28a5ec01d15703794a31accd08d 我的文件2
d28b9f7fc7d61c60913c8026fc91149a 我的文件3
→ md5sum --check 我的总和
我的文件: OK
我的文件2: OK
我的文件3: OK
→ echo "新数据" > 我的文件2
→ md5sum --check 我的总和
我的文件: OK
我的文件2: 失败
我的文件3: OK
md5sum: 警告:3个计算的校验和有1个不匹配
两个不同的文件极不可能有相同的MD5校验和,所以比较校验和是检测两个文件是否不同的一个相当可靠的方式:
→ md5sum 我的文件 | cut -c1-32 > 总和1
→ md5sum 我的文件2 | cut -c1-32 > 总和2
→ diff -q 总和1 总和2
总和1和总和2有差异
一个更强大但(暂时)不太受欢迎的程序是shasum
,它可以使用不同的算法生成更长的哈希。它可能比md5sum
更可靠。
→ shasum 我的文件 SHA-1算法
253c9c5836261859a77f83dc296168b35c1230ac 我的文件
→ shasum -a 256 我的文件 SHA-256算法
e8183aaa23aa9b74c7033cbc843041fcf1d1e9e93724b7ef63c94d4c50a15df8 我的文件
→ shasum 我的文件 > 我的总和
→ shasum --check 我的总和
我的文件: OK
推荐阅读
你好,我是拾叁,7年开发老司机、互联网两年外企5年。怼得过阿三老美,也被PR comments搞崩溃过。这些年我打过工,创过业,接过私活,也混过upwork。赚过钱也亏过钱。一路过来,给我最深的感受就是不管学什么,一定要不断学习。只要你能坚持下来,就很容易实现弯道超车!所以,不要问我现在干什么是否来得及。如果你还没什么方向,可以先关注我,这里会经常分享一些前沿资讯和编程知识,帮你积累弯道超车的资本。